{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a56dec3d",
   "metadata": {},
   "source": [
    "# Variational Quantum Algorithms in Q\\#"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96818c17",
   "metadata": {},
   "source": [
    "## Abstract"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c55ddd55",
   "metadata": {},
   "source": [
    "In this sample, we will explore how the rich classical control provided by Q# can be used to efficiently write out variational quantum algorithms. In particular, we'll focus on the example of the _variational quantum eigensolver_, also known as VQE."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4fc6c47b",
   "metadata": {},
   "source": [
    "## Preamble\n",
    "\n",
    "$\n",
    "    \\renewcommand{\\ket}[1]{\\left|#1\\right\\rangle}\n",
    "$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b6e73483",
   "metadata": {},
   "outputs": [],
   "source": [
    "from itertools import product, repeat, starmap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "11fa63fc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Preparing Q# environment...\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import qutip as qt\n",
    "import qsharp"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a80f41f",
   "metadata": {},
   "source": [
    "For Q# code embedded in this notebook, it will be helpful to open a few namespaces before we proceed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "373cb753",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "open Microsoft.Quantum.Arrays;\n",
    "open Microsoft.Quantum.Characterization;\n",
    "open Microsoft.Quantum.Convert;\n",
    "open Microsoft.Quantum.Diagnostics;\n",
    "open Microsoft.Quantum.Random;\n",
    "open Microsoft.Quantum.Math;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dce084a9",
   "metadata": {},
   "source": [
    "## Introducing the Variational Quantum Eigensolver"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "983fbce7",
   "metadata": {},
   "source": [
    "In variational quantum algorithms, rather than performing all of our computation on the quantum device itself, we use a quantum program to estimate some quantity, then use a classical optimizer to find inputs to our quantum program that minimize or maximize that quantity. That is, rather than thinking of classical computation purely as a pre-processing or post-processing step, our computation uses both classical and quantum computation together."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "150b8540",
   "metadata": {},
   "source": [
    "> **💡 TIP:** We could also consider using classical computation while qubits are still alive, rather than returning an estimate to a classical optimizer. This approach is indeed very useful, for instance in iterative phase estimation. For this sample, however, we'll focus on the variational case."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f8c35bf",
   "metadata": {},
   "source": [
    "\n",
    "For example, consider the problem of finding the _ground state energy_ of a given operator $H$, often called a _Hamiltonian_. The ground state energy of $H$ is defined as its smallest eigenvalue $E_0$, as the Hamiltonian represents the possible energy configurations of a given physical system.\n",
    "\n",
    "As stated, even though this is a minimization, we need to know the eigenvalues of $H$ to make any progress. It's pretty straightforward to rephrase the problem in terms of arbitrary states, however. In particular, the expectation value $\\left\\langle H \\right\\rangle H = \\left\\langle \\psi | H | \\psi \\right\\rangle$ must be at least as large as $E_0$. To see this, we can expand the expectation value in terms of the eigenvectors $\\{\\ket{\\phi_i}\\}$ of $H$, such that $H\\ket{\\phi_i} = E_i$.\n",
    "\n",
    "Since the decomposition of $H$ into eigenvectors gives us a basis, we know that $\\left\\langle \\phi_i | \\phi_j \\right\\rangle$ is zero whenever $i \\ne j$, allowing us to expand $\\ket{\\psi}$ into the eigenbasis of $H$ as $\\ket{\\psi} = \\sum_i \\alpha_i \\ket{\\phi_i}$ for some complex coefficients $\\{\\alpha_i\\}$. Using this decomposition, we can expand the expectation $\\left\\langle \\psi | H | \\psi \\right\\rangle$ in terms of the eigenvalues of $H$:\n",
    "\n",
    "$$\n",
    "\\begin{aligned}\n",
    "    \\left\\langle \\psi | H | \\psi \\right\\rangle\n",
    "        & = \\sum_i |\\alpha_i|^2 \\left\\langle \\phi_i | H | \\phi_i \\right\\rangle \\\\\n",
    "        & = \\sum_i |\\alpha_i|^2 \\left\\langle \\phi_i | E_i \\phi_i \\right\\rangle \\\\\n",
    "        & = \\sum_i |\\alpha_i|^2 E_i.\n",
    "\\end{aligned}\n",
    "$$\n",
    "\n",
    "Since each $|\\alpha_i|^2$ is nonnegative, and since $\\sum_i |\\alpha_i|^2 = 1$, the above gives us that\n",
    "$$\n",
    "    E_0 = \\min_i E_i \\le \\left\\langle \\psi | H | \\psi \\right\\rangle \\le \\max_i E_i.\n",
    "$$\n",
    "\n",
    "Thus, we can rephrase the original problem as a minimization not just over eigenstates, but of all arbitrary states,\n",
    "$$\n",
    "    E_0 = \\min_{\\ket{\\psi}} \\left\\langle \\psi | H | \\psi \\right\\rangle,\n",
    "$$\n",
    "where the minimum is achieved when $\\ket{\\psi} = \\ket{\\phi_0}$.\n",
    "\n",
    "Using this rephrasing, the _variational quantum eigensolver_ algorithm is just the variational algorithm that we get by using a classical optimizer to find $\\min_{\\ket{\\psi}} \\left\\langle \\psi | H | \\psi \\right\\rangle$. In pseudocode:\n",
    "\n",
    "```\n",
    "operation FindMinimumEigenvalue {\n",
    "    Pick an initial guess |ψ⟩.\n",
    "    until target accuracy reached {\n",
    "        Estimate E = ⟨ψ | H | ψ⟩ using a quantum operation.\n",
    "        Use a classical optimizer to pick the next |ψ⟩.\n",
    "    }\n",
    "    Return the minimum E that we found and the state |ψ⟩ that achieved that minimum.\n",
    "}\n",
    "```"
   ]
  },
  {
   "attachments": {
    "vqe.png": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "id": "41037e71",
   "metadata": {},
   "source": [
    "![vqe.png](attachment:vqe.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68e94097",
   "metadata": {},
   "source": [
    "To turn the above pseudocode into a real quantum program, we still need to figure out two things:\n",
    "\n",
    "- How to estimate $\\left\\langle \\psi | H | \\psi \\right\\rangle$ for a given state $\\ket{\\psi}$.\n",
    "- How to optimize over all quantum states $\\ket{\\psi}$.\n",
    "\n",
    "In the rest of this sample, we'll see how to do each of these, and how you can use Q# to write a VQE implementation."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f7b662b",
   "metadata": {},
   "source": [
    "## Estimating expectation values of $H$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3bb1ba6",
   "metadata": {},
   "source": [
    "Before proceeding to see how to estimate $\\left\\langle \\psi | H | \\psi \\right\\rangle$, however, it helps to consider what that expectation value _is_. To do so, let's consider a concrete example of a two-qubit Hamiltonian, using QuTiP to construct a Python object representing $H$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a992fe41",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "Quantum object: dims = [[2, 2], [2, 2]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}-2.0 & 0.0 & 0.0 & 3.0\\\\0.0 & 7.0 & 0.0 & 1.0\\\\0.0 & 0.0 & -4.0 & 0.0\\\\3.0 & 1.0 & 0.0 & -1.0\\\\\\end{array}\\right)\\end{equation*}"
      ],
      "text/plain": [
       "Quantum object: dims = [[2, 2], [2, 2]], shape = (4, 4), type = oper, isherm = True\n",
       "Qobj data =\n",
       "[[-2.  0.  0.  3.]\n",
       " [ 0.  7.  0.  1.]\n",
       " [ 0.  0. -4.  0.]\n",
       " [ 3.  1.  0. -1.]]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "H = qt.Qobj([\n",
    "    [-2, 0, 0, 3],\n",
    "    [0, 7, 0, 1],\n",
    "    [0, 0, -4, 0],\n",
    "    [3, 1, 0, -1]\n",
    "], dims=[[2, 2]] * 2)\n",
    "H"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b09b667",
   "metadata": {},
   "source": [
    "Here, `H` is a Python object representing the 4 × 4 matrix $H$. We can use the `eigenstates` method provided by QuTiP to quickly find the eigenvalues and eigenvectors of $H$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "33551a8c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([-4.57776672, -4.        ,  1.43800535,  7.13976137]),\n",
       " array([Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\n",
       "        Qobj data =\n",
       "        [[ 0.75726547]\n",
       "         [ 0.05620122]\n",
       "         [ 0.        ]\n",
       "         [-0.65068458]]                                                    ,\n",
       "        Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\n",
       "        Qobj data =\n",
       "        [[ 0.]\n",
       "         [ 0.]\n",
       "         [-1.]\n",
       "         [ 0.]]                                                            ,\n",
       "        Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\n",
       "        Qobj data =\n",
       "        [[-0.65152827]\n",
       "         [ 0.13424187]\n",
       "         [ 0.        ]\n",
       "         [-0.74665256]]                                                    ,\n",
       "        Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\n",
       "        Qobj data =\n",
       "        [[0.04538633]\n",
       "         [0.9893536 ]\n",
       "         [0.        ]\n",
       "         [0.13827341]]                                                     ],\n",
       "       dtype=object))"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "H.eigenstates()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba4c191e",
   "metadata": {},
   "source": [
    "In particular, we can use the `min` function provided by Python to minimize over the eigenvalues of $H$ and find its ground state $\\ket{\\phi_0}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3199b955",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-4.577766724471026,\n",
       " Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\n",
       " Qobj data =\n",
       " [[ 0.75726547]\n",
       "  [ 0.05620122]\n",
       "  [ 0.        ]\n",
       "  [-0.65068458]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "min_energy, ground_state = min(zip(*H.eigenstates()), key=lambda eig: eig[0])\n",
    "min_energy, ground_state"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ce8638c",
   "metadata": {},
   "source": [
    "Here, `ground_state` represents the eigenvector $\\ket{\\phi_0}$ corresponding to the smallest eigenvalue $E_0$ of $H$. By the above argument, we would expect that $\\left\\langle \\phi_0 | H | \\phi_0 \\right\\rangle = E_0$. We can check that using QuTiP as well:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a2140642",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-4.577766724471031+0j)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(ground_state.dag() * H * ground_state)[0, 0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "853df02f",
   "metadata": {},
   "source": [
    "What's going on here? Effectively, for any operator $O$ such that $O^{\\dagger} = O$, expressions like $\\left\\langle \\psi | O | \\psi \\right\\rangle$ represent another way of thinking about quantum measurement. In particular, if we think of the eigenvalues of $O$ as labels for its corresponding various eigenvectors, then $\\left\\langle \\psi | O | \\psi \\right\\rangle$ is the average label that we get when we measure $O$ in the basis of its eigenvectors."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8537e34c",
   "metadata": {},
   "source": [
    "> **💡 TIP:** This way of thinking about quantum measurement is sometimes called the _observable framework_, with $O$ being called an _observable_. We avoid using this terminology here to avoid confusion, however, as the expectation value of $O$ cannot be observed directly, but only inferred from repeated measurements."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "817f94ec",
   "metadata": {},
   "source": [
    "For example, if $O = Z$, then the eigenstate $\\ket{0}$ is labeled by its eigenvalue $+1$, while $\\ket{1}$ is labeled by $-1$. The expectation value $\\left\\langle \\psi | Z | \\psi \\right\\rangle$ is then the probability of getting a `Zero` minus the probability of getting a `One`.\n",
    "\n",
    "More generally, finding the expectation value of an arbitrary Pauli operator for an arbitrary input state is straightforward using the `Measure` and `EstimateFrequencyA` operations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d6558958",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation EstimatePauliExpectation(pauli : Pauli[], preparation : (Qubit[] => Unit is Adj), nShots : Int) : Double {\n",
    "    return 2.0 * EstimateFrequencyA(\n",
    "        preparation,\n",
    "        Measure(pauli, _),\n",
    "        Length(pauli),\n",
    "        nShots\n",
    "    ) - 1.0;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d07f00c",
   "metadata": {},
   "source": [
    "Here, we've represented the state $\\ket{\\psi}$ by an operation `preparation` that prepares that state. Since each Pauli operator other than the identity operator has exactly two eigenvalues, $+1$ and $-1$, corresponding to `Zero` and `One` respectively, we can turn the estimate of the probability $p_0$ with which `Measure(pauli, _)` returns `Zero` into an expectation value $p_0 - p_1 = p_0 - (1 - p_0) = 2 p_0 - 1$.\n",
    "\n",
    "For example, doing nothing prepares the state $\\ket{0}$, so we get an expectation value of $1$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "22a23913",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation EstimateExpectationOfZero() : Double {\n",
    "    return EstimatePauliExpectation(\n",
    "        [PauliZ],\n",
    "        NoOp,\n",
    "        100\n",
    "    );\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "1135713f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "EstimateExpectationOfZero.simulate()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aef4f547",
   "metadata": {},
   "source": [
    "Similarly, using `X` to prepare $\\ket{1}$ gives us an expectation of $-1$, while using `H` to prepare $\\ket{+} = \\frac{1}{\\sqrt{2}} (\\ket{0} + \\ket{1})$ gives an expectation value of $0$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "8dbf0842",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation EstimateExpectationOfOne() : Double {\n",
    "    return EstimatePauliExpectation(\n",
    "        [PauliZ],\n",
    "        ApplyToEachCA(X, _),\n",
    "        100\n",
    "    );\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "2cab1fca",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.0"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "EstimateExpectationOfOne.simulate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "408d1da3",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation EstimateExpectationOfPlus() : Double {\n",
    "    return EstimatePauliExpectation(\n",
    "        [PauliZ],\n",
    "        ApplyToEachCA(H, _),\n",
    "        100\n",
    "    );\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "fc6d8273",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.08000000000000007"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "EstimateExpectationOfPlus.simulate()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d023ef6",
   "metadata": {},
   "source": [
    "Note that in practice, we won't always get exactly 0 due to using a finite number of measurements."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2d9316d",
   "metadata": {},
   "source": [
    "In any case, to recap, it's easy to use a quantum program to find $\\left\\langle \\psi | H | \\psi \\right\\rangle$ in the special case that $H$ is a multi-qubit Pauli operator. What about the more general case? The linearity of quantum mechanics saves us again! It turns out that we can expand the expectation of any other operator in terms of expectations of Pauli operators. To see how that works, suppose that $H = 2 Z - X$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "ae9236c7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}2.0 & -1.0\\\\-1.0 & -2.0\\\\\\end{array}\\right)\\end{equation*}"
      ],
      "text/plain": [
       "Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\n",
       "Qobj data =\n",
       "[[ 2. -1.]\n",
       " [-1. -2.]]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2 * qt.sigmaz() - qt.sigmax()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d7db2d3",
   "metadata": {},
   "source": [
    "We can expand $\\left\\langle \\psi | (2Z - X) | \\psi \\right\\rangle$ by using linearity:\n",
    "\n",
    "$$\n",
    "    \\left\\langle \\psi | (2Z - X) | \\psi \\right\\rangle = 2 \\left\\langle \\psi | Z | \\psi \\right\\rangle - \\left\\langle \\psi | X | \\psi \\right\\rangle.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "797bd006",
   "metadata": {},
   "source": [
    "Each of the terms in this expansion is something that we can estimate easily using our `EstimatePauliExpectation` operation from above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "d10b40ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation EstimateExpectation(terms : (Double, Pauli[])[], preparation : (Qubit[] => Unit is Adj), nShots : Int) : Double {\n",
    "    mutable sum = 0.0;\n",
    "    for (coefficient, pauli) in terms {\n",
    "        set sum += coefficient * EstimatePauliExpectation(\n",
    "            pauli, preparation, nShots\n",
    "        );\n",
    "    }\n",
    "    return sum;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49bf9fcc",
   "metadata": {},
   "source": [
    "With this, we almost have everything we need to estimate expectations $\\left\\langle \\psi | H | \\psi \\right\\rangle$. We just need a way of finding the decomposition of $H$ into Pauli operators. Thankfully, QuTiP can help here as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "731556db",
   "metadata": {},
   "outputs": [],
   "source": [
    "def pauli_basis(n_qubits):\n",
    "    scale = 2 ** n_qubits\n",
    "    return {\n",
    "        tuple(P): qt.tensor(*(p.as_qobj() for p in P)) / scale\n",
    "        for P in product(qsharp.Pauli, repeat=n_qubits)\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "c8e0b922",
   "metadata": {},
   "outputs": [],
   "source": [
    "def expand_in_pauli_basis(op):\n",
    "    return [\n",
    "        (coeff, list(label))\n",
    "        for label, coeff in {\n",
    "            label: (P.dag() * op).tr()\n",
    "            for label, P in pauli_basis(n_qubits=len(op.dims[0])).items()\n",
    "        }.items()\n",
    "        if abs(coeff) >= 1e-10\n",
    "    ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff5c27bc",
   "metadata": {},
   "source": [
    "For example, we can use the two functions above to find that $H = -3 𝟙 \\otimes Z + 0.5 X \\otimes 𝟙 + 1.5 X \\otimes X - 0.5 X \\otimes Z - 1.5 Y \\otimes Y + 2.5 Z \\otimes 𝟙 - 1.5 Z \\otimes Z$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "cd8e5438",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(-3.0, [<Pauli.I: 0>, <Pauli.Z: 2>]),\n",
       " (0.5, [<Pauli.X: 1>, <Pauli.I: 0>]),\n",
       " (1.5, [<Pauli.X: 1>, <Pauli.X: 1>]),\n",
       " (-0.5, [<Pauli.X: 1>, <Pauli.Z: 2>]),\n",
       " (-1.5, [<Pauli.Y: 3>, <Pauli.Y: 3>]),\n",
       " (2.5, [<Pauli.Z: 2>, <Pauli.I: 0>]),\n",
       " (-1.5, [<Pauli.Z: 2>, <Pauli.Z: 2>])]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "H_decomposition = expand_in_pauli_basis(H)\n",
    "H_decomposition"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8879b674",
   "metadata": {},
   "source": [
    "This decomposition is exactly what we need to pass as `terms` above. For example, to estimate the expectation of the $\\ket{++}$ state, $\\left\\langle ++ | H | ++ \\right\\rangle$, we can pass `terms` to `EstimateExpectation`. In doing so, we'll use the name \"energy\" for our new operation, pointing to that expectation values of Hamiltonian operators $H$ represent the average energy of a system given the quantum state of that system."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "fad87b56",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation EstimateEnergyOfPlus(terms : (Double, Pauli[])[]) : Double {\n",
    "    return EstimateExpectation(\n",
    "        terms,\n",
    "        ApplyToEachCA(H, _),\n",
    "        100\n",
    "    );\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "1f0e22df",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.7599999999999998"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "EstimateEnergyOfPlus.simulate(terms=H_decomposition)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29a48a9f",
   "metadata": {},
   "source": [
    "This is pretty far from the minimum $E_0$ we found from the eigenvalue decomposition above, so in the next part we'll see one more trick we can use to write our VQE implementation."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bfad16a",
   "metadata": {},
   "source": [
    "## Preparing ansatz states"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ae1ddfe",
   "metadata": {},
   "source": [
    "Recall that our goal is to use a classical optimizer to find the minimum energy $E_0$ of some Hamiltonian operator $H$:\n",
    "$$\n",
    "    E_0 = \\min_{\\ket{\\psi}} \\left\\langle \\psi | H | \\psi \\right\\rangle.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe83f982",
   "metadata": {},
   "source": [
    "In practice, we can't reasonably optimize over all possible quantum states $\\ket{\\psi}$, so that the above optimization problem is intractable for all but the smallest systems. Instead, we note that we can find an upper-bound for $E_0$ by solving a simpler problem. Suppose that there is a set $A$ of states that are easier to prepare. Then,\n",
    "$$\n",
    "    E_0 = \\min_{\\ket{\\psi}} \\left\\langle \\psi | H | \\psi \\right\\rangle \\le \\min_{\\ket{\\psi} \\in A} \\left\\langle \\psi | H | \\psi \\right\\rangle.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3926dbbf",
   "metadata": {},
   "source": [
    "If we choose $A$ carefully so that $\\ket{\\phi_0} \\in A$, this inequality will be tight. More often, however, $\\ket{\\phi_0}$ won't actually be in $A$, but will be close to some other state in $A$, giving us a reasonable approximation to $E_0$."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6bce67e",
   "metadata": {},
   "source": [
    "We say that $A$ is our _ansatz_ for running VQE; in this way, $A$ plays a similar role to a model in an ML training loop, representing what we believe to be a reasonable set of guesses for $\\ket{\\phi_0}$. One can get pretty involved with their choice of ansatz, but for this sample, we'll choose a really simple one, and set $A$ to be those states that can be prepared by a small number of Pauli rotations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "950a5184",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation PrepareAnsatz(axes : Pauli[][], angles : Double[], register : Qubit[]) : Unit is Adj {\n",
    "    for (axis, angle) in Zipped(axes, angles) {\n",
    "        Exp(axis, angle, register);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b377850f",
   "metadata": {},
   "source": [
    "Our minimization $\\min_{\\ket{\\psi} \\in A} \\left\\langle \\psi | H | \\psi \\right\\rangle$ is now a minimization over `angles` for some fixed list of Pauli rotation axes. Using `DumpMachine` and `DumpRegister`, we can visualize how this ansatz works for a few different choices of parameters `angles`, convincing ourselves that $A$ contains enough interesting states to find $E_0$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "ec65a772",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation DumpAnsatz(axes : Pauli[][], angles : Double[]) : Unit {\n",
    "    use register = Qubit[Length(angles)];\n",
    "    within {\n",
    "        PrepareAnsatz(axes, angles, register);\n",
    "    } apply {\n",
    "        DumpRegister((), register);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "b99c1d78",
   "metadata": {},
   "outputs": [],
   "source": [
    "ansatz_axes = [[qsharp.Pauli.Z, qsharp.Pauli.Z], [qsharp.Pauli.X, qsharp.Pauli.Y]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "7df99a83",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/x-qsharp-data": "{\"diagnostic_kind\":\"state-vector\",\"div_id\":\"dump-machine-div-9f284d8d-23ab-410c-9594-177dc366a0f2\",\"qubit_ids\":[0,1],\"n_qubits\":2,\"amplitudes\":[{\"Real\":-0.11714648149439554,\"Imaginary\":-0.3013185124022002,\"Magnitude\":0.3232895668635034,\"Phase\":-1.9415926535897934},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":-0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":3.141592653589793},{\"Real\":-0.3428991748354909,\"Imaginary\":-0.881988668778884,\"Magnitude\":0.9463000876874147,\"Phase\":-1.9415926535897934}]}",
      "text/html": [
       "\r\n",
       "                    <table style=\"table-layout: fixed; width: 100%\">\r\n",
       "                        <thead>\r\n",
       "                            \r\n",
       "                        <tr>\r\n",
       "                            <th>Qubit IDs</th>\r\n",
       "                            <td span=\"3\">0, 1</td>\r\n",
       "                        </tr>\r\n",
       "                    \r\n",
       "                            <tr>\r\n",
       "                                <th style=\"width: 20ch)\">Basis state (bitstring)</th>\r\n",
       "                                <th style=\"width: 20ch\">Amplitude</th><th style=\"width: calc(100% - 26ch - 20ch)\">Meas. Pr.</th><th style=\"width: 6ch\">Phase</th>\r\n",
       "                            </tr>\r\n",
       "                        </thead>\r\n",
       "                        <tbody>\r\n",
       "                        \r\n",
       "                            <tr>\r\n",
       "                                <td>$\\left|00\\right\\rangle$</td>\r\n",
       "                                <td>$-0.1171  -0.3013 i$</td>\r\n",
       "                                \r\n",
       "                                <td>\r\n",
       "                                    <progress\r\n",
       "                                        max=\"100\"\r\n",
       "                                        value=\"10.451614404279164\"\r\n",
       "                                        style=\"width: 100%;\"\r\n",
       "                                    > \r\n",
       "                                    <td>\r\n",
       "                                    <p id=\"round-a3620649-7e0d-4644-aba8-64d52c78a7b9\"> \r\n",
       "                                    <script>\r\n",
       "                                    var num = 10.451614404279164;\r\n",
       "                                    num = num.toFixed(4);\r\n",
       "                                    var num_string = num + \"%\";\r\n",
       "                                     document.getElementById(\"round-a3620649-7e0d-4644-aba8-64d52c78a7b9\").innerHTML = num_string;\r\n",
       "                                    </script> </p>\r\n",
       "                                    </td>\r\n",
       "                                </td>\r\n",
       "                            \r\n",
       "                                \r\n",
       "                                <td style=\"transform: rotate(-111.24506458430123deg);\r\n",
       "                   text-align: center;\">\r\n",
       "                                 ↑\r\n",
       "                                </td>\r\n",
       "                            \r\n",
       "                            </tr>\r\n",
       "                        \n",
       "\r\n",
       "                            <tr>\r\n",
       "                                <td>$\\left|11\\right\\rangle$</td>\r\n",
       "                                <td>$-0.3429  -0.8820 i$</td>\r\n",
       "                                \r\n",
       "                                <td>\r\n",
       "                                    <progress\r\n",
       "                                        max=\"100\"\r\n",
       "                                        value=\"89.54838559572087\"\r\n",
       "                                        style=\"width: 100%;\"\r\n",
       "                                    > \r\n",
       "                                    <td>\r\n",
       "                                    <p id=\"round-c0986bfe-a430-42a8-a610-c9cb21a4125d\"> \r\n",
       "                                    <script>\r\n",
       "                                    var num = 89.54838559572087;\r\n",
       "                                    num = num.toFixed(4);\r\n",
       "                                    var num_string = num + \"%\";\r\n",
       "                                     document.getElementById(\"round-c0986bfe-a430-42a8-a610-c9cb21a4125d\").innerHTML = num_string;\r\n",
       "                                    </script> </p>\r\n",
       "                                    </td>\r\n",
       "                                </td>\r\n",
       "                            \r\n",
       "                                \r\n",
       "                                <td style=\"transform: rotate(-111.24506458430123deg);\r\n",
       "                   text-align: center;\">\r\n",
       "                                 ↑\r\n",
       "                                </td>\r\n",
       "                            \r\n",
       "                            </tr>\r\n",
       "                        \r\n",
       "                        </tbody>\r\n",
       "                    </table>"
      ],
      "text/plain": [
       "|00⟩\t-0.11714648149439554 + -0.3013185124022002𝑖\n",
       "|11⟩\t-0.3428991748354909 + -0.881988668778884𝑖"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "DumpAnsatz.simulate(axes=ansatz_axes, angles=[1.2, 1.9])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "fc79ef91",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/x-qsharp-data": "{\"diagnostic_kind\":\"state-vector\",\"div_id\":\"dump-machine-div-0a397bc2-bfa5-4a90-92c7-be1e7a06f23b\",\"qubit_ids\":[0,1],\"n_qubits\":2,\"amplitudes\":[{\"Real\":0.27714649751343473,\"Imaginary\":0.7128628131458088,\"Magnitude\":0.7648421872844886,\"Phase\":1.2},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.23343727454160576,\"Imaginary\":0.600436064376938,\"Magnitude\":0.644217687237691,\"Phase\":1.2}]}",
      "text/html": [
       "\r\n",
       "                    <table style=\"table-layout: fixed; width: 100%\">\r\n",
       "                        <thead>\r\n",
       "                            \r\n",
       "                        <tr>\r\n",
       "                            <th>Qubit IDs</th>\r\n",
       "                            <td span=\"3\">0, 1</td>\r\n",
       "                        </tr>\r\n",
       "                    \r\n",
       "                            <tr>\r\n",
       "                                <th style=\"width: 20ch)\">Basis state (bitstring)</th>\r\n",
       "                                <th style=\"width: 20ch\">Amplitude</th><th style=\"width: calc(100% - 26ch - 20ch)\">Meas. Pr.</th><th style=\"width: 6ch\">Phase</th>\r\n",
       "                            </tr>\r\n",
       "                        </thead>\r\n",
       "                        <tbody>\r\n",
       "                        \r\n",
       "                            <tr>\r\n",
       "                                <td>$\\left|00\\right\\rangle$</td>\r\n",
       "                                <td>$0.2771 + 0.7129 i$</td>\r\n",
       "                                \r\n",
       "                                <td>\r\n",
       "                                    <progress\r\n",
       "                                        max=\"100\"\r\n",
       "                                        value=\"58.49835714501207\"\r\n",
       "                                        style=\"width: 100%;\"\r\n",
       "                                    > \r\n",
       "                                    <td>\r\n",
       "                                    <p id=\"round-b47890f6-267c-46fa-a468-3c6d6610ef99\"> \r\n",
       "                                    <script>\r\n",
       "                                    var num = 58.49835714501207;\r\n",
       "                                    num = num.toFixed(4);\r\n",
       "                                    var num_string = num + \"%\";\r\n",
       "                                     document.getElementById(\"round-b47890f6-267c-46fa-a468-3c6d6610ef99\").innerHTML = num_string;\r\n",
       "                                    </script> </p>\r\n",
       "                                    </td>\r\n",
       "                                </td>\r\n",
       "                            \r\n",
       "                                \r\n",
       "                                <td style=\"transform: rotate(68.75493541569878deg);\r\n",
       "                   text-align: center;\">\r\n",
       "                                 ↑\r\n",
       "                                </td>\r\n",
       "                            \r\n",
       "                            </tr>\r\n",
       "                        \n",
       "\r\n",
       "                            <tr>\r\n",
       "                                <td>$\\left|11\\right\\rangle$</td>\r\n",
       "                                <td>$0.2334 + 0.6004 i$</td>\r\n",
       "                                \r\n",
       "                                <td>\r\n",
       "                                    <progress\r\n",
       "                                        max=\"100\"\r\n",
       "                                        value=\"41.50164285498795\"\r\n",
       "                                        style=\"width: 100%;\"\r\n",
       "                                    > \r\n",
       "                                    <td>\r\n",
       "                                    <p id=\"round-618d4c20-4d72-473b-ba10-e6fe32d64707\"> \r\n",
       "                                    <script>\r\n",
       "                                    var num = 41.50164285498795;\r\n",
       "                                    num = num.toFixed(4);\r\n",
       "                                    var num_string = num + \"%\";\r\n",
       "                                     document.getElementById(\"round-618d4c20-4d72-473b-ba10-e6fe32d64707\").innerHTML = num_string;\r\n",
       "                                    </script> </p>\r\n",
       "                                    </td>\r\n",
       "                                </td>\r\n",
       "                            \r\n",
       "                                \r\n",
       "                                <td style=\"transform: rotate(68.75493541569878deg);\r\n",
       "                   text-align: center;\">\r\n",
       "                                 ↑\r\n",
       "                                </td>\r\n",
       "                            \r\n",
       "                            </tr>\r\n",
       "                        \r\n",
       "                        </tbody>\r\n",
       "                    </table>"
      ],
      "text/plain": [
       "|00⟩\t0.27714649751343473 + 0.7128628131458088𝑖\n",
       "|11⟩\t0.23343727454160576 + 0.600436064376938𝑖"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "DumpAnsatz.simulate(axes=ansatz_axes, angles=[1.2, -0.7])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d2f1e81",
   "metadata": {},
   "source": [
    "At this point, it's helpful to write some new operations that directly estimate the energy of a state given a parameterization of our ansatz, rather than an opaque operation that prepares the state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "11583999",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "operation EstimateEnergyAtAnsatz(terms : (Double, Pauli[])[], axes : Pauli[][], angles : Double[], nShots : Int) : Double {\n",
    "    return EstimateExpectation(\n",
    "        terms,\n",
    "        PrepareAnsatz(axes, angles, _),\n",
    "        nShots\n",
    "    );\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "418ace1a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.6689999999999996"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "EstimateEnergyAtAnsatz.simulate(\n",
    "    terms=H_decomposition,\n",
    "    axes=ansatz_axes,\n",
    "    angles=[1.2, 1.9],\n",
    "    nShots=1000\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f07737a",
   "metadata": {},
   "source": [
    "## Running VQE in Q\\#"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0970ee4",
   "metadata": {},
   "source": [
    "Using this new operation, we have something that looks much more like classical optimization problems that we may be used to! Indeed, we can simply use our favorite optimization algorithm to pick different values for `angles` until we find a good approximation for $E_0$. In this sample, we'll use the _SPSA algorithm_ to optimize `angles`, as this algorithm works especially well for objective functions that have some amount of noise, such as that added by taking a finite number of shots above.\n",
    "\n",
    "We won't go through the details of SPSA here, but if you're interested to learn more, check out [`Optimization.qs`](../edit/Optimization.qs) in this folder to see how we implemented SPSA in Q#."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "7f3049df",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "\n",
    "open Microsoft.Quantum.Samples;\n",
    "\n",
    "operation FindMinimumEnergy(terms : (Double, Pauli[])[], axes : Pauli[][], initialGuess : Double[], nShots : Int) : (Double[], Double) {\n",
    "    let oracle = EstimateEnergyAtAnsatz(terms, axes, _, nShots);\n",
    "    let options = DefaultSpsaOptions();\n",
    "    return FindMinimumWithSpsa(\n",
    "        oracle,\n",
    "        initialGuess,\n",
    "        options\n",
    "    );\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "337c5318",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration 1:\r\n",
      "\tobj([1.3,1.7999999999999998]) = 0.23789999999999933\n",
      "\tobj([1.0999999999999999,2]) = 1.0606999999999989\r\n",
      "Iteration 2:\r\n",
      "\tobj([5.4072386486436805,-2.3072386486436804]) = -4.443300000000001\n",
      "\tobj([5.220761351356314,-2.120761351356314]) = -3.9806999999999997\r\n",
      "Iteration 3:\r\n",
      "\tobj([7.037902178086054,-3.937902178086054]) = 1.5017999999999998\n",
      "\tobj([6.858907240214701,-3.7589072402147017]) = 1.1875999999999998\r\n",
      "Iteration 4:\r\n",
      "\tobj([5.9554488934051255,-2.8554488934051263]) = -3.5013\n",
      "\tobj([6.12931780542313,-3.0293178054231302]) = -2.6095\r\n",
      "Iteration 5:\r\n",
      "\tobj([3.9009690359209475,-0.8009690359209479]) = 1.5058999999999996\n",
      "\tobj([3.730974866762821,-0.6309748667628211]) = 1.2235\r\n",
      "Iteration 6:\r\n",
      "\tobj([3.2689680723727736,-0.16896807237277411]) = -1.0234999999999999\n",
      "\tobj([3.102075611160924,-0.002075611160924487]) = -2.0348000000000006\r\n",
      "Iteration 7:\r\n",
      "\tobj([1.0427526924439467,1.8929331087197825]) = 0.6591000000000005\n",
      "\tobj([1.207066891280217,2.0572473075560525]) = 1.2284000000000006\r\n",
      "Iteration 8:\r\n",
      "\tobj([0.13218195359203944,0.8202493458908133]) = -4.464700000000001\n",
      "\tobj([-0.029931070385022407,0.9823623698678752]) = -4.104799999999999\r\n",
      "Iteration 9:\r\n",
      "\tobj([0.6059251921980732,0.3465061072847796]) = -3.7606000000000006\n",
      "\tobj([0.7661211311159201,0.18631016836693268]) = -3.016\r\n",
      "Iteration 10:\r\n",
      "\tobj([-0.6315032091450663,1.583934508627919]) = -0.9689999999999999\n",
      "\tobj([-0.47300294304897195,1.4254342425318245]) = -1.8338000000000005\r\n",
      "Iteration 11:\r\n",
      "\tobj([0.8904618284608332,0.2189512818433449]) = -3.1862000000000004\n",
      "\tobj([0.7334800176395078,0.061969471022019454]) = -2.3197\r\n",
      "Iteration 12:\r\n",
      "\tobj([2.1929443481764768,1.5214338015589883]) = -1.2516999999999996\n",
      "\tobj([2.037336072654365,1.3658255260368766]) = -2.1906\r\n",
      "Iteration 13:\r\n",
      "\tobj([0.6861404394380952,0.1689852535657936]) = -2.9084999999999996\n",
      "\tobj([0.8404958001832821,0.01462989282060681]) = -2.0399000000000003\r\n",
      "Iteration 14:\r\n",
      "\tobj([-0.5584389822919025,1.2603603367711584]) = -2.804899999999999\n",
      "\tobj([-0.4052346437672696,1.4135646752957913]) = -1.9059000000000006\r\n",
      "Iteration 15:\r\n",
      "\tobj([-1.7560801113150146,0.0627192077480463]) = -2.340299999999999\n",
      "\tobj([-1.603939632580259,0.21485968648280185]) = -3.1656\r\n",
      "Iteration 16:\r\n",
      "\tobj([-0.521515017729757,1.1461323085016812]) = -3.3974\n",
      "\tobj([-0.6726670105613797,1.297284301333304]) = -2.5974\r\n",
      "Iteration 17:\r\n",
      "\tobj([0.32502558530933495,0.29959170546258934]) = -3.561499999999999\n",
      "\tobj([0.4752548891036687,0.1493624016682556]) = -2.8175999999999997\r\n",
      "Iteration 18:\r\n",
      "\tobj([-0.5741010280293131,1.0493537901721766]) = -3.8229\n",
      "\tobj([-0.42473649940025227,1.1987183188012374]) = -3.1506\r\n",
      "Iteration 19:\r\n",
      "\tobj([-1.2523030595356437,0.37115175866584577]) = -3.8564\n",
      "\tobj([-1.400854162931055,0.22260065527043466]) = -3.2044\r\n",
      "Iteration 20:\r\n",
      "\tobj([-0.5069904589222417,1.1164643592792478]) = -3.5358\n",
      "\tobj([-0.6547739651268821,0.9686808530746074]) = -4.1446\r\n",
      "Iteration 21:\r\n",
      "\tobj([-1.1859767586449395,0.43747805955654995]) = -4.1025\n",
      "\tobj([-1.3330338077053359,0.29042101049615376]) = -3.5204000000000004\r\n",
      "Iteration 22:\r\n",
      "\tobj([-0.7166834873381936,0.9067713308632959]) = -4.3034\n",
      "\tobj([-0.5703157683120065,1.053139049889483]) = -3.8239\r\n",
      "Iteration 23:\r\n",
      "\tobj([-1.097005649592668,0.5264491686088213]) = -4.3238\n",
      "\tobj([-1.2427177049506681,0.38073711325082144]) = -3.8923\r\n",
      "Iteration 24:\r\n",
      "\tobj([-0.7939437107895229,0.9745981606865233]) = -4.1282\n",
      "\tobj([-0.6488566575149664,0.8295111074119668]) = -4.4505\r\n",
      "Iteration 25:\r\n",
      "\tobj([-0.3212528291041481,0.5019072790011485]) = -4.2675\n",
      "\tobj([-0.4657429168429572,0.6463973667399576]) = -4.5222\r\n",
      "Iteration 26:\r\n",
      "\tobj([-0.575419917146314,0.7560743670433144]) = -4.5154\n",
      "\tobj([-0.7193387696142085,0.8999932195112089]) = -4.319100000000001\r\n",
      "Iteration 27:\r\n",
      "\tobj([-0.38383182531047444,0.5644862752074747]) = -4.4421\n",
      "\tobj([-0.5272031359796895,0.7078575858766899]) = -4.531600000000001\r\n",
      "Iteration 28:\r\n",
      "\tobj([-0.6127783483513505,0.6505871433444893]) = -4.5236\n",
      "\tobj([-0.46993269344748895,0.7934327982483508]) = -4.5151\r\n",
      "Iteration 29:\r\n",
      "\tobj([-0.4930703410206383,0.7702951506752015]) = -4.5054\n",
      "\tobj([-0.635410615146146,0.6279548765496937]) = -4.5112\r\n",
      "Iteration 30:\r\n",
      "\tobj([-0.6405344031497799,0.6228310885460598]) = -4.507099999999999\n",
      "\tobj([-0.49868067673746364,0.7646848149583761]) = -4.5098\r\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "([-0.5671511573010752, 0.6962143343947645], -4.5329)"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "FindMinimumEnergy.simulate(terms=H_decomposition, axes=ansatz_axes, initialGuess=[1.2, 1.9], nShots=10_000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "d6276b06",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-4.577766724471026"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "min_energy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "97fbc5df",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "464ea5c5cae2889b0c59ecc40909802f0909ef10120e6598fbb774b74247ba9f"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
